package day29.ioFile;

import java.io.File;

/**
 * FileTest2类用于演示如何遍历文件系统目录结构
 * 该类提供了递归遍历指定目录及其所有子目录的功能，
 * 并以树状结构形式输出目录和文件信息，包括文件大小
 */
public class FileTest2 {

    /**
     * 程序入口点 - main方法
     * 负责初始化测试实例并调用目录遍历方法
     * @param args 命令行参数数组，本程序中未使用
     */
    public static void main(String[] args) {
        // 创建FileTest2类的实例，用于调用非静态方法
        // 这种方式遵循了面向对象编程的原则，避免在main方法中直接调用静态方法
        FileTest2 test = new FileTest2();
        
        // 遍历当前项目根目录的代码已被注释掉，因为在实际使用中可能输出过多信息
        //System.out.println("遍历当前项目根目录");
        //test.traverseDirectory(".");
        
        // 调用traverseDirectory方法遍历"day29"目录及其所有子目录
        // 这会在控制台输出目录结构树和每个文件的大小信息
        System.out.println("\n遍历day29目录");
        test.traverseDirectory("day29");
    }
    
    /**
     * 公共接口方法，用于启动对指定目录的遍历过程
     * 这是一个包装方法，为递归遍历提供初始调用点
     * @param dirPath 要遍历的目录路径字符串，可以是相对路径或绝对路径
     */
    public void traverseDirectory(String dirPath) {
        // 创建File对象，表示要遍历的目录
        // File类是Java中文件和目录路径名的抽象表示，用于文件系统操作
        File dir = new File(dirPath);
        
        // 调用递归辅助方法开始遍历，初始深度设置为0（根目录层级）
        traverseDirectoryHelper(dir, 0);
    }
    
    /**
     * 递归遍历目录的核心实现方法
     * 使用递归算法深度优先遍历目录树结构，输出每个文件和目录的信息
     * @param dir 表示当前要遍历的目录的File对象
     * @param depth 当前遍历的深度层级，用于控制输出的缩进量，根目录为0
     */
    private void traverseDirectoryHelper(File dir, int depth) {
        // 检查目录是否存在，这是文件操作前的重要验证步骤
        // exists()方法用于测试此抽象路径名表示的文件或目录是否存在
        if (!dir.exists()) {
            // 如果目录不存在，输出错误信息并返回，避免后续操作引发异常
            System.out.println("目录不存在: " + dir.getAbsolutePath());
            return;
        }
        
        // 检查指定路径是否为目录而非文件
        // isDirectory()方法用于测试此抽象路径名表示的文件是否为目录
        if (!dir.isDirectory()) {
            // 如果路径指向的是文件而不是目录，输出相应提示信息并返回
            System.out.println("指定路径不是目录: " + dir.getAbsolutePath());
            return;
        }
        
        // 创建用于输出缩进的StringBuilder对象
        // 使用StringBuilder而非String是因为需要频繁修改字符串内容，StringBuilder效率更高
        StringBuilder indent = new StringBuilder();
        
        // 根据当前深度构建相应数量的空格缩进
        // 每增加一级深度，缩进增加两个空格，这样可以清晰地显示目录层级结构
        for (int i = 0; i < depth; i++) {
            // append方法用于在StringBuilder末尾添加指定字符串
            indent.append("  ");
        }
        
        // 输出当前目录名称，使用方括号标识这是一个目录而非文件
        // getName()方法返回由此抽象路径名表示的文件或目录的名称
        System.out.println(indent.toString() + "[" + dir.getName() + "]");
        
        // 获取目录中的所有文件和子目录，返回File对象数组
        // listFiles()方法返回一个抽象路径名数组，表示此抽象路径名表示的目录中的文件
        File[] files = dir.listFiles();
        
        // 检查files数组是否为null（可能由于安全限制或I/O错误导致）
        if (files != null) {
            // 遍历当前目录中的每个文件和子目录
            for (File file : files) {
                // 判断当前项是目录还是文件
                if (file.isDirectory()) {
                    // 如果是目录，则递归调用此方法遍历该子目录
                    // 递归深度加1，以增加下一级的缩进量
                    traverseDirectoryHelper(file, depth + 1);
                } else {
                    // 如果是文件，则输出文件名和大小信息
                    // getName()获取文件名，length()获取文件大小（以字节为单位）
                    System.out.println(indent.toString() + "  " + file.getName() + 
                                     " (" + file.length() + " bytes)");
                }
            }
        } else {
            // 如果listFiles()返回null，说明无法访问目录内容（可能由于权限问题）
            System.out.println(indent.toString() + "  无法访问目录内容");
        }
    }
}